package com.hh.mybatis.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.hh.common.core.domain.BaseEntity;
import com.hh.mybatis.service.IBaseService;
import com.hh.mybatis.utils.ReflectUtil;
import com.mybatisflex.core.BaseMapper;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;

/**
 * BaseService层处理
 *
 * @author hh
 * @date 2023-03-17
 */
public abstract class BaseServiceImpl<T extends BaseEntity> implements IBaseService<T> {
    @Resource
    private SqlSessionFactory sqlSessionFactory;

    private Class<BaseMapper<T>> currentMapperClass() {
        return ReflectUtil.getMapperTarget(getBaseMapper());
    }

    /**
     * 先校验后修改
     *
     * @param entity 实体
     * @return 结果
     */
    @Override
    public boolean add(T entity) {
        checkSave(entity);
        return save(entity);
    }

    /**
     * 先校验后修改
     *
     * @param entity 实体
     * @return 结果
     */
    @Override
    public boolean edit(T entity)
    {
        checkEdit(entity);
        return updateById(entity);
    }

    /**
     * 批量新增
     *
     * @param list
     */
    @Override
    public void batchInsert(final List<T> list) {
        if (CollUtil.isEmpty(list)) {
            return;
        }
        try (SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH, false)) {
            BaseMapper mapper = session.getMapper(currentMapperClass());
            int batch = 0;
            for (T record : list) {
                mapper.insertSelective(record);
                batch++;
                if (batch == 800) {
                    session.commit();
                    session.clearCache();
                    batch = 0;
                }
            }
            session.commit();
        }
    }

    /**
     * TODO min 批量更新性能提升不大，待跟进处理
     * 批量更新
     *
     * @param list
     */
    @Override
    public void batchUpdate(final List<T> list) {
        if (CollUtil.isEmpty(list)) {
            return;
        }
        try (SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH, false)) {
            BaseMapper mapper = session.getMapper(currentMapperClass());
            int batch = 0;
            for (T record : list) {
                mapper.update(record);
                batch++;
                if (batch == 800) {
                    session.commit();
                    session.clearCache();
                    batch = 0;
                }
            }
            session.commit();
        }
    }

    /**
     * 批量更新删除 此方法防止用deleteByIds时候，in中id集合超长
     *
     * @param ids
     */
    @Override
    public void batchDelete(final Collection<? extends Serializable> ids) {
        if (CollUtil.isEmpty(ids)) {
            return;
        }
        try (SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH, false)) {
            BaseMapper mapper = session.getMapper(currentMapperClass());
            int batch = 0;
            for (Serializable record : ids) {
                mapper.deleteById(record);
                batch++;
                if (batch == 800) {
                    session.commit();
                    session.clearCache();
                    batch = 0;
                }
            }
            session.commit();
        }
    }

    /**
     * 新增前校验
     * @param entity
     */
    protected void checkSave(T entity)
    {
    }

    public void checkEdit(T entity)
    {
    }
}
